#pragma once
#include "Base.h"

namespace System
{

/*******************************************************/
class Type
{
private:
	TCHAR* m_TypeName;

public:
	Type(const TCHAR* typeName);
	~Type();

public:
	const TCHAR* ToString() const;
	const TCHAR* GetFullName() const;
	static const Type* GetType();
};

DEFINE_CLASS_TYPE(System_Type, _T("System::Type"));
/*******************************************************/

class XObject
{

public:
	XObject();
	virtual ~XObject();

public:
	VIRTUAL_GET_TYPE();
	VIRTUAL_TOSTRING();
};

DEFINE_CLASS_TYPE(System_XObject, _T("System::XObject"));
/*******************************************************/

#ifndef MEMSTR_DEFAULT_SIZE
#define MEMSTR_DEFAULT_SIZE 64
#endif

class MemString : public XObject
{
private:
	TCHAR* m_Buffer;
	size_t m_Length;
	size_t m_Capacity;

public:
	MemString(void);
	MemString(const size_t size);
	MemString(const TCHAR* pstr);
	MemString(const TCHAR* pstr, const size_t size);
	MemString(const MemString& str);
	~MemString(void);

private:
	void Release();
	void Default();
	void Init(const size_t size);
	void Increase(const size_t len);

public:
	MemString& operator +(const TCHAR ch);
	MemString& operator +(const TCHAR* pstr);
	MemString& operator +(const MemString str);

	MemString& operator +=(const TCHAR ch);
	MemString& operator +=(const TCHAR* pstr);
	MemString& operator +=(const MemString str);

	MemString& operator =(const TCHAR ch);
	MemString& operator =(const TCHAR* pstr);


public:
	void Reset();
	const size_t Size();
	const TCHAR* GetData() const;

	static inline size_t StrLen(const TCHAR* str) {
		size_t len = 0;

		if(str != NULL) {
			while(str[len]!=0) len++;
		}

		return len;
	}

public:
	VIRTUAL_GET_TYPE();
	VIRTUAL_TOSTRING();
};

typedef MemString* MemStringPtr;
typedef const MemString* CMemStringPtr;

DEFINE_CLASS_TYPE(System_MemString, _T("System::MemString"));

/*******************************************************/
#ifndef DEFAULT_POINTER_LIST_SIZE
#define DEFAULT_POINTER_LIST_SIZE 4
#endif

template<typename T>
class PointerList
{
private:
	T* m_Container;
	size_t m_Size;
	size_t m_Capacity;

private:
	void Init(const size_t size)
	{
		this->m_Size = 0;
		this->m_Capacity = size > 0 ? size : DEFAULT_POINTER_LIST_SIZE;
		this->m_Container = new T[this->m_Capacity];
		memset(this->m_Container, 0, this->m_Capacity);
	}

	void Increase(const size_t len)
	{
		size_t total = this->m_Size + len;
		if(total > this->m_Capacity)
		{
			T* buffer = new T[total];
			memset(buffer, 0, total);
			if(this->m_Container != NULL) {
				memcpy(buffer, this->m_Container, this->m_Size*sizeof(T));
				delete this->m_Container;
			}

			this->m_Container = buffer;
			this->m_Capacity = total;
		}
	}

public:
	PointerList() { Init(0); }
	virtual ~PointerList()
	{
		if(this->m_Container != NULL) {
			for(size_t i = 0; i < this->m_Size; i++) {
				delete this->m_Container[i];
			}
			this->m_Size = 0;

			delete this->m_Container;
			this->m_Container = NULL;
		}
	}

public:
	size_t Size() { return this->m_Size; }
	size_t Capacity() { return this->m_Capacity; }

	T GetItem(int index) {
		if(this->m_Size > 0 && index < this->m_Size) {
			return this->m_Container[index];
		}

		return NULL;
	}

	void Add(T val)
	{
		if(val != NULL) {
			if(this->m_Size + 1 >= this->m_Capacity) { 
				this->Increase(this->m_Capacity);
			}
			this->m_Container[this->m_Size++] = val;
		}
	}

	void Remove(int index)
	{
		if(this->m_Size > 0 && index < this->m_Size) {
			if(this->m_Container[index] != NULL) {
				delete this->m_Container[index];
				for(size_t i = index + 1; i < this->m_Size; i++) {
					this->m_Container[i - 1] = this->m_Container[i];
				}

				this->m_Container[this->m_Size - 1] = NULL;
				this->m_Size--;
			}
		}
	}
};

/*******************************************************/


}// end namespace